//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 


#include "disc.h"

Define_Module(disc);

void disc::initialize(){

    this->discFree = true;
    this->queueRequeriments.setName("queueReq");
    this->latecyTime = 0;
    this->searchTime = 0;
    this->tranferTime = par("tranferTime");
    this->processTime = 0;

    this->responseTimeStadistic = new cStdDev("responseTimeDisc");
    this->discUsedTime = 0;
    this->queueMeanSize = 0;
    this->currentTime = 0;
    this->prevTime = 0;

    this->currentRequirement = NULL;

}
void disc::handleMessage(cMessage *msg){
    if (strcmp(msg->getName(),"Requirement") == 0){
        requirement = (Requirement*) msg;
        bubble("Access to Disc");
        if(currentRequirement == NULL)
            currentRequirement = requirement;
        else
            queueRequeriments.insert(requirement);
        processQueueMeanSize();
    }else if(strcmp(msg->getName(),"endReq") == 0){
        discFree = true;
        currentRequirement->setTimeOut(simTime());
        simtime_t responseMeanTime = (currentRequirement->getTimeOut() - currentRequirement->getTimeIn());
        responseTimeStadistic->collect(responseMeanTime);
        send(currentRequirement, "outDisc");
        currentRequirement = NULL;
        delete msg;
    }
    if (currentRequirement == NULL and !queueRequeriments.isEmpty()){
        currentRequirement = (Requirement*) queueRequeriments.pop();
        processQueueMeanSize();
        processRequeriment();
    }else if (currentRequirement != NULL and discFree){
        processRequeriment();
    }
}
void disc::processRequeriment(){
    discFree = false;
    latecyTime = par("latecyTime");
    //http://www.omnetpp.org/doc/omnetpp/api/group__RandomNumbersCont.html#g420c4783712a2f1742e3c3e240810f64
    searchTime = par("searchTime");//beta(0.01,0.025,0);
    processTime = tranferTime+searchTime+latecyTime;
    discUsedTime = discUsedTime + processTime;
    currentRequirement->setName("finishedRequirement");
    //currentRequirement->setTimeOut(processTime);
    cMessage* endReq = new cMessage("endReq");
    scheduleAt(simTime()+processTime, endReq);
}

void disc::processQueueMeanSize(){
    double auxCurrentTime = simTime().dbl();
    currentTime = auxCurrentTime - prevTime;
    queueMeanSize = queueMeanSize + (currentTime*queueRequeriments.length());
    prevTime = auxCurrentTime;
}

void disc::finish(){
    ev<<"*********************************"<<endl;
    ev<<"DISC: "<<this->getId()<<endl;
    ev<<"Rho:"<<discUsedTime/simTime()<<endl;
    ev<<"L:"<<queueMeanSize/simTime()<<endl;
    ev<<"W:"<<responseTimeStadistic->getMean()<<endl;
}
